home *** CD-ROM | disk | FTP | other *** search
/ Programming Windows 95 with MFC / Programming Windows 95 with MFC (Microsoft Programming Series)(097-0001465)(1996).iso / CODE / Chap04 / Paint2 / Paint2.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-05  |  7.3 KB  |  290 lines

  1. //***********************************************************************
  2. //
  3. //  Paint2.cpp
  4. //
  5. //***********************************************************************
  6.  
  7. #define OEMRESOURCE
  8.  
  9. #include <afxwin.h>
  10. #include "Resource.h"
  11. #include "Paint2.h"
  12.  
  13. CMyApp myApp;
  14.  
  15. /////////////////////////////////////////////////////////////////////////
  16. // CMyApp member functions
  17.  
  18. BOOL CMyApp::InitInstance ()
  19. {
  20.     m_pMainWnd = new CMainWindow;
  21.     m_pMainWnd->ShowWindow (m_nCmdShow);
  22.     m_pMainWnd->UpdateWindow ();
  23.     return TRUE;
  24. }
  25.  
  26. /////////////////////////////////////////////////////////////////////////
  27. // CMainWindow message map and member functions
  28.  
  29. BEGIN_MESSAGE_MAP (CMainWindow, CFrameWnd)
  30.     ON_WM_PAINT ()
  31.     ON_COMMAND (IDM_FILE_NEW, OnFileNew)
  32.     ON_COMMAND (IDM_FILE_EXIT, OnFileExit)
  33.     ON_COMMAND_RANGE (IDM_WIDTH_VTHIN, IDM_WIDTH_VTHICK, OnWidth)
  34.     ON_COMMAND_RANGE (IDM_COLOR_BLACK, IDM_COLOR_WHITE, OnColor)
  35.     ON_UPDATE_COMMAND_UI (IDM_FILE_NEW, OnUpdateFileNewUI)
  36.     ON_UPDATE_COMMAND_UI_RANGE (IDM_WIDTH_VTHIN, IDM_WIDTH_VTHICK,
  37.         OnUpdateWidthUI)
  38.     ON_UPDATE_COMMAND_UI_RANGE (IDM_COLOR_BLACK, IDM_COLOR_WHITE,
  39.         OnUpdateColorUI)
  40.     ON_WM_LBUTTONDOWN ()
  41.     ON_WM_MOUSEMOVE ()
  42.     ON_WM_LBUTTONUP ()
  43.     ON_WM_CONTEXTMENU ()
  44.     ON_WM_MEASUREITEM ()
  45.     ON_WM_DRAWITEM ()
  46. END_MESSAGE_MAP ()
  47.  
  48. const COLORREF CMainWindow::crColors[8] = {
  49.     RGB (  0,   0,   0),    // Black
  50.     RGB (  0,   0, 255),    // Blue
  51.     RGB (  0, 255,   0),    // Green
  52.     RGB (  0, 255, 255),    // Cyan
  53.     RGB (255,   0,   0),    // Red
  54.     RGB (255,   0, 255),    // Magenta
  55.     RGB (255, 255,   0),    // Yellow
  56.     RGB (255, 255, 255)     // White
  57. };
  58.  
  59. CMainWindow::CMainWindow ()
  60. {
  61.     m_nColor = IDM_COLOR_RED;
  62.     m_nWidth = IDM_WIDTH_MEDIUM;
  63.     m_lineArray.SetSize (0, 64);
  64.  
  65.     CString strWndClass = AfxRegisterWndClass (
  66.         0,
  67.         myApp.LoadStandardCursor (IDC_CROSS),
  68.         (HBRUSH) (COLOR_WINDOW + 1),
  69.         myApp.LoadIcon (IDR_MAINFRAME)
  70.     );
  71.     
  72.     Create (strWndClass, "Paint2", WS_OVERLAPPEDWINDOW,
  73.         rectDefault, NULL, MAKEINTRESOURCE (IDR_MAINFRAME));
  74.  
  75.     LoadAccelTable (MAKEINTRESOURCE (IDR_MAINFRAME));
  76.  
  77.     CMenu* pMenu = GetMenu ();
  78.     for (int i=0; i<8; i++)
  79.         pMenu->ModifyMenu (IDM_COLOR_BLACK + i, MF_BYCOMMAND |
  80.             MF_OWNERDRAW, IDM_COLOR_BLACK + i);
  81. }
  82.  
  83. CMainWindow::~CMainWindow ()
  84. {
  85.     DeleteAllLines ();
  86. }
  87.  
  88. void CMainWindow::OnPaint ()
  89. {
  90.     CPaintDC dc (this);
  91.     int nCount = m_lineArray.GetSize ();
  92.  
  93.     if (nCount) {
  94.         for (int i=0; i<nCount; i++)
  95.             ((CLine*) m_lineArray[i])->Draw (&dc);
  96.     }
  97. }
  98.  
  99. void CMainWindow::OnFileNew ()
  100. {
  101.     DeleteAllLines ();
  102.     Invalidate ();
  103. }
  104.  
  105. void CMainWindow::OnUpdateFileNewUI (CCmdUI* pCmdUI)
  106. {
  107.     pCmdUI->Enable (m_lineArray.GetSize ());
  108. }
  109.  
  110. void CMainWindow::OnFileExit ()
  111. {
  112.     SendMessage (WM_CLOSE, 0, 0);
  113. }
  114.  
  115. void CMainWindow::OnWidth (UINT nID)
  116. {
  117.     m_nWidth = nID;
  118. }
  119.  
  120. void CMainWindow::OnColor (UINT nID)
  121. {
  122.     m_nColor = nID;
  123. }
  124.  
  125. void CMainWindow::OnUpdateWidthUI (CCmdUI* pCmdUI)
  126. {
  127.     pCmdUI->SetCheck (pCmdUI->m_nID == m_nWidth);
  128. }
  129.  
  130. void CMainWindow::OnUpdateColorUI (CCmdUI* pCmdUI)
  131. {
  132.     pCmdUI->SetCheck (pCmdUI->m_nID == m_nColor);
  133. }
  134.  
  135. void CMainWindow::OnLButtonDown (UINT nFlags, CPoint point)
  136. {
  137.     m_ptFrom = point;
  138.     m_ptTo = point;
  139.     SetCapture ();
  140. }
  141.  
  142. void CMainWindow::OnMouseMove (UINT nFlags, CPoint point)
  143. {
  144.     if (GetCapture () == this) {
  145.         CClientDC dc (this);
  146.         InvertLine (&dc, m_ptFrom, m_ptTo);
  147.         InvertLine (&dc, m_ptFrom, point);
  148.         m_ptTo = point;
  149.     }
  150. }
  151.  
  152. void CMainWindow::OnLButtonUp (UINT nFlags, CPoint point)
  153. {
  154.     static UINT nWidths[5] = { 1, 8, 16, 24, 32 };
  155.  
  156.     if (GetCapture () == this) {
  157.         ReleaseCapture ();
  158.  
  159.         CClientDC dc (this);
  160.         InvertLine (&dc, m_ptFrom, m_ptTo);
  161.         CLine* pLine = NULL;
  162.  
  163.         try {
  164.             pLine = new CLine (m_ptFrom, m_ptTo,
  165.                 nWidths[m_nWidth - IDM_WIDTH_VTHIN],
  166.                 crColors[m_nColor - IDM_COLOR_BLACK]);
  167.  
  168.             m_lineArray.Add (pLine);
  169.             pLine->Draw (&dc);
  170.         }
  171.         catch (CMemoryException* e) {
  172.             MessageBox ("Out of memory. You must clear the " \
  173.                 "drawing area before adding more lines.", "Error",
  174.                 MB_ICONEXCLAMATION | MB_OK);
  175.  
  176.             if (pLine != NULL)
  177.                 delete pLine;
  178.             e->Delete ();   
  179.         }       
  180.     }
  181. }
  182.  
  183. void CMainWindow::OnContextMenu (CWnd* pWnd, CPoint point)
  184. {
  185.     CRect rect;
  186.     GetClientRect (&rect);
  187.     ClientToScreen (&rect);
  188.  
  189.     if (rect.PtInRect (point)) {
  190.         CMenu menu;
  191.         menu.LoadMenu (IDR_CONTEXTMENU);
  192.         CMenu* pContextMenu = menu.GetSubMenu (0);
  193.  
  194.         for (int i=0; i<8; i++)
  195.             pContextMenu->ModifyMenu (IDM_COLOR_BLACK + i,
  196.                 MF_BYCOMMAND | MF_OWNERDRAW, IDM_COLOR_BLACK + i);
  197.  
  198.         pContextMenu->TrackPopupMenu (TPM_LEFTALIGN | TPM_LEFTBUTTON |
  199.             TPM_RIGHTBUTTON, point.x, point.y, this);
  200.         return;
  201.     }
  202.     CFrameWnd::OnContextMenu (pWnd, point);
  203. }
  204.  
  205. void CMainWindow::OnMeasureItem (int nIDCtl, LPMEASUREITEMSTRUCT lpmis)
  206. {
  207.     lpmis->itemWidth = ::GetSystemMetrics (SM_CYMENU) * 4;
  208.     lpmis->itemHeight = ::GetSystemMetrics (SM_CYMENU);
  209. }
  210.  
  211. void CMainWindow::OnDrawItem (int nIDCtl, LPDRAWITEMSTRUCT lpdis)
  212. {
  213.     BITMAP bm;
  214.     CBitmap bitmap;
  215.     bitmap.LoadOEMBitmap (OBM_CHECK);
  216.     bitmap.GetObject (sizeof (bm), &bm);
  217.  
  218.     CDC dc;
  219.     dc.Attach (lpdis->hDC);
  220.  
  221.     CBrush* pBrush = new CBrush (::GetSysColor ((lpdis->itemState &
  222.         ODS_SELECTED) ? COLOR_HIGHLIGHT : COLOR_MENU));
  223.     dc.FrameRect (&(lpdis->rcItem), pBrush);
  224.     delete pBrush;
  225.  
  226.     if (lpdis->itemState & ODS_CHECKED) {
  227.         CDC dcMem;
  228.         dcMem.CreateCompatibleDC (&dc);
  229.         CBitmap* pOldBitmap = dcMem.SelectObject (&bitmap);
  230.  
  231.         dc.BitBlt (lpdis->rcItem.left + 4, lpdis->rcItem.top +
  232.             (((lpdis->rcItem.bottom - lpdis->rcItem.top) -
  233.             bm.bmHeight) / 2), bm.bmWidth, bm.bmHeight, &dcMem,
  234.             0, 0, SRCCOPY);
  235.  
  236.         dcMem.SelectObject (pOldBitmap);
  237.     }
  238.  
  239.     pBrush = new CBrush (crColors[lpdis->itemID - IDM_COLOR_BLACK]);
  240.     CRect rect = lpdis->rcItem;
  241.     rect.DeflateRect (6, 4);
  242.     rect.left += bm.bmWidth;
  243.     dc.FillRect (rect, pBrush);
  244.     delete pBrush;
  245.  
  246.     dc.Detach ();
  247. }
  248.  
  249. void CMainWindow::InvertLine (CDC* pDC, CPoint ptFrom, CPoint ptTo)
  250. {
  251.     int nOldMode = pDC->SetROP2 (R2_NOT);
  252.  
  253.     pDC->MoveTo (ptFrom);
  254.     pDC->LineTo (ptTo);
  255.  
  256.     pDC->SetROP2 (nOldMode);
  257. }
  258.  
  259. void CMainWindow::DeleteAllLines ()
  260. {
  261.     int nCount = m_lineArray.GetSize ();
  262.  
  263.     for (int i=0; i<nCount; i++)
  264.         delete m_lineArray[i];
  265.  
  266.     m_lineArray.RemoveAll ();
  267. }
  268.  
  269. /////////////////////////////////////////////////////////////////////////
  270. // CLine member functions
  271.  
  272. CLine::CLine (CPoint ptFrom, CPoint ptTo, UINT nWidth, COLORREF crColor)
  273. {
  274.     m_ptFrom = ptFrom;
  275.     m_ptTo = ptTo;
  276.     m_nWidth = nWidth;
  277.     m_crColor = crColor;
  278. }
  279.  
  280. void CLine::Draw (CDC* pDC)
  281. {
  282.     CPen pen (PS_SOLID, m_nWidth, m_crColor);
  283.  
  284.     CPen* pOldPen = pDC->SelectObject (&pen);
  285.     pDC->MoveTo (m_ptFrom);
  286.     pDC->LineTo (m_ptTo);
  287.  
  288.     pDC->SelectObject (pOldPen);
  289. }
  290.